/*
    This file is part of SQLiteGTK, written by Aly Hirani

    SQLiteGTK is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SQLiteGTK is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SQLiteGTK.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "include.h"
#include "guid.h"
#include "util.h"

inline gboolean valid_hex(gchar c)
{
	return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}

void guid_free(GUID *guid)
{
	g_assert(guid);
	g_assert(guid->guid);
	
	g_free(guid->guid);
	g_free(guid);
}

GUID* guid_new(const gchar *guid)
{
	glong len;
	glong i, j = 0;
	gchar *new_guid;
	GUID *new_guid_struct;
	
	D_ASSERT(guid);
	
	len = MIN(g_ascii_strlen(guid), 38);
	
	if(len == 0)
		return NULL;
	
	new_guid = g_malloc(38);
	
	D_ASSERT(new_guid);

	/* The initial bracket */
	if(guid[0] != '{')
	{
		new_guid[j++] = '{';
	}
	
	for(i = 0; i < len; ++i)
	{
		/* The separator */
		if(j == 9 || j == 14 || j == 19 || j == 24)
		{
			if(guid[i] != '-')
			{
				new_guid[j++] = '-';
			}
		}
		else
		{
			/* Make sure the separator is not at a wrong place */
			if(guid[i] == '-')
				break;
		}
		
		/* The validation of the char itself */
		if(!(valid_hex(guid[i]) || guid[i] == '-' || guid[i] == '{' || guid[i] == '}'))
			break;
		
		/* Copy the char. To standardize it, convert it to uppercase */
		new_guid[j++] = g_ascii_toupper(guid[i]);
	}
	
	if(guid[len - 1] != '}')
	{
		new_guid[j++] = '}';
	}
	
	if(j != 38)
	{
		g_free(new_guid);
		return NULL;
	}
	
	new_guid_struct = g_malloc_type(GUID);
	R_ASSERT(new_guid_struct);
	
	new_guid_struct->guid = new_guid;
	
	return new_guid_struct;
}

gboolean guid_equal(const GUID* guid1, const GUID* guid2)
{
	D_ASSERT(guid1);
	D_ASSERT(guid2);

	/* This is a slight performance hack. This prevents us from matching the strings if we can judge that the guids
	   are actually the same objects in memory */
	if(guid1 == guid2)
		return TRUE;

	return g_str_equal(guid1->guid, guid2->guid);
}

gint guid_compare(const GUID* guid1, const GUID* guid2)
{
	D_ASSERT(guid1);
	D_ASSERT(guid2);

	/* Performance hack */
	if(guid1 == guid2)
	{
		return 0;
	}

	return g_strcmp0(guid1->guid, guid2->guid);
}
